package com.jdk.demo.nio.bytebuffer;

import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;

public class TestByteBuffer {

	private static ByteBuffer byteBuffer = null;
    public  static void main(String[] args) {
            /* 以下顺序不要改变*/
            initByteBuffer();
            testByte();
            testChar();
            testMark();
            testInt();
            testFloat();
            testDouble();
            testLong();
            testCh();
            testRemaining();
            testOverFlow();
            testReset();
            testClear();
            // limit代表第一个不应该读取或写入元素的index
            // 从控制台输出可看出，ByteBuffer的put*和get*（int index）方法不改变mark，limit和capacity的值;put则回改变position的位置，put操作后position的位置为，put操作之前position+length（put 操作数）；mark操作会改变mark的值，reset操作，则是将position定位到mark；clear操作并不会清空缓冲空间，而是将position复位0，limit为capacity，mark为-1；remain操作返回的是可用的空间大小为capacity-position；
            // 如put后，超出缓冲区大小，则抛出BufferOverflowException异常
    }
    /**
     * 初始化缓存空间
		position:0
		limit:32
		capacity:32
     */
     public static void initByteBuffer(){
         byteBuffer  = ByteBuffer.allocate(32);
         System.out.println("===============init status============");
         System.out.println("position:"+byteBuffer.position());
         System.out.println("limit:"+byteBuffer.limit());
         System.out.println("capacity:"+byteBuffer.capacity());
      }
     /**
      * 测试Byte，占用一个字节
      * position:1
		limit:32
		capacity:32
		======get byte:102
      */
     public static void testByte(){
         System.out.println("===============put byte============");
         //字节
         byte bbyte = 102;
         // java.nio.HeapByteBuffer[pos=1 lim=32 cap=32]
         byteBuffer.put(bbyte);//ByteBuffer
         byteBuffer.get(0);//byte
         System.out.println("position:"+byteBuffer.position());
         System.out.println("limit:"+byteBuffer.limit());
         System.out.println("capacity:"+byteBuffer.capacity());
         System.out.println("======get byte:"+byteBuffer.get(0));
     }
     /**
      * 测试Char，占用2个字节
      * position:3
		limit:32
		capacity:32
		======get Char:a
      */
     public static void testChar(){
    	 System.out.println("===============put char============");
         //字符
         char aChar= 'a';
         // java.nio.HeapByteBuffer[pos=3 lim=32 cap=32]
         byteBuffer.putChar(aChar);
         System.out.println("position:"+byteBuffer.position());
         System.out.println("limit:"+byteBuffer.limit());
         System.out.println("capacity:"+byteBuffer.capacity());
         System.out.println("======get Char:"+byteBuffer.getChar(1));
     }
     /**
      * 标记位置，以便reset，返回这个标记位置
      * position:5
		limit:32
		capacity:32
		position:3
		limit:32
		capacity:32
      */
      public static void testMark(){
          //标记位置
    	  // java.nio.HeapByteBuffer[mark=3 pos=3 lim=32 cap=32]
          byteBuffer.mark();
          char aChar= 'a';
          byteBuffer.putChar(aChar);
          System.out.println("===============mark============");
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          // java.nio.HeapByteBuffer[mark=3 pos=3 lim=32 cap=32]
          // position回到当时mark的位置
          byteBuffer.reset();
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
      }
      /**
       * 测试int，占用4个字节
       * position:7
		limit:32
		capacity:32
		======get int:4
       */
      public static void testInt(){
          System.out.println("===============put int============");
          //int
          int int4 = 4;
          byteBuffer.putInt(int4);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第三个字节开始读取，因为前面一个字节和一个字符总共三个字节
          System.out.println("======get int:"+byteBuffer.getInt(3));
      }
      /**
       * 测试float，占用4个字节
       * position:11
		limit:32
		capacity:32
		======get float:10.0
       */
      public static void testFloat(){
          System.out.println("===============put float============");
          //float
          float float5 = 10;
          byteBuffer.putFloat(float5);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第7个字节开始读取，因为前面一个字节和一个字符，一个int总共7个字节
          System.out.println("======get float:"+byteBuffer.getFloat(7));
      }
      /**
       * 测试double，占用8个字节
       * position:19
		limit:32
		capacity:32
		======get double:20.0
       */
      public static void testDouble(){
          System.out.println("===============put double============");
          //double
          double double6 = 20.0;
          byteBuffer.putDouble(double6);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第11个字节开始读取，因为前面一个字节和一个字符，一个int,一个float总共11个字节
          System.out.println("======get double:"+byteBuffer.getDouble(11));
      }
      /**
       * 测试Long，占用8个字节
       * position:27
		limit:32
		capacity:32
		======get long:30
       */
      public static void testLong(){
          System.out.println("===============put long============");
          //long
          long long7 = (long) 30.0;
          byteBuffer.putLong(long7);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第19个字节开始读取，因为前面一个字节和一个字符，一个int,一个float，一个double总共19个字节
          System.out.println("======get long:"+byteBuffer.getLong(19));
      }

      /**
     * position:29
		limit:32
		capacity:32
		======get long:我
     */
    public static void testCh(){
          System.out.println("===============put 中文============");
          char a = '我';
          byteBuffer.putChar(a);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get long:"+byteBuffer.getChar(27));
      }

      /**
       * 测试字节缓冲的剩余空间函数
       * ======buffer 剩余空间大小:3
       */
      public static void testRemaining(){
          System.out.println("======buffer 剩余空间大小:"+byteBuffer.remaining());
      }
      /**
       * 测试添加元素字节长度，大于剩余空间时的情况
       */
      public static void testOverFlow(){
          /*Exception in thread "main" java.nio.BufferOverflowException
            at java.nio.Buffer.nextPutIndex(Buffer.java:519)
            at java.nio.HeapByteBuffer.putLong(HeapByteBuffer.java:417)
            at socket.TestByteBuffer.main(TestByteBuffer.java:60)
            超出空间，则抛出BufferOverflowException异常
            */
         try{
           byteBuffer.putLong((long)30.0);
         }
         catch(BufferOverflowException e){
           // e.printStackTrace();
        	 System.out.println("java.nio.BufferOverflowException");
         }
      }
      /**
       * 测试回到标记，position为标记的mark
       * position:3
		limit:32
		capacity:32
		======get  int from mark:4
		position:7
		limit:32
		capacity:32
		======get int from mark after put new int value:5
       */
      public static void testReset(){
         System.out.println("===============reset============");
          //回到mark标记位置，position为标记的mark
          byteBuffer.reset();
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get  int from mark:"+byteBuffer.getInt(3));
          //重新，从标记位置put一个int值，原来的内容被覆盖掉
          int int5 = 5;
          byteBuffer.putInt(int5);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get int from mark after put new int value:"+byteBuffer.getInt(3));
      }
      /**
       * clear重置position，mark，limit位置，原始缓存区内容并不清掉
       * position:0
		limit:32
		capacity:32
		======get int  after clear:5
       */
      public static void testClear(){
          System.out.println("===============clear============");
          //clear重置position，mark，limit位置，原始缓存区内容并不清掉
          byteBuffer.clear();
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get int  after clear:"+byteBuffer.getInt(3));

      }

}
